<?php
$loader->requireOnce('includes/inPatientCore/InPatientCoreErrorCode.class.php');
$loader->requireOnce('includes/inPatientCore/InPatientCoreException.class.php');
$loader->requireOnce('includes/BedManagement/BedManagement.class.php');
$loader->requireOnce('ordo/InPatient.class.php');
$loader->requireOnce('ordo/PatientTransferHistory.class.php');

$loader->requireOnce('includes/inPatientCore/TestDiagnosisTicketManagement.class.php');


/**
 * Inpatient Processor.
 * @package core.includes.inPatientCore
 * @author viethd
 * @version $Id$
 * @copyright 2009 LHV Company
 */
class TreatingPatientProcessor {
	protected $controller;

	protected $inPatientObj;	
	private $logger ;
	protected $bedMg;

	/**
	 *
	 * @param $controller controller for build ui
	 */
	function __construct($controller) {
		$this->logger = LoggerManager::getLogger('core.inPatientCore.TreatingPatientProcessor');
		$this->controller = $controller;
		$this->inPatientObj = Celini::newORDO("InPatient");
		$this->bedMg = new BedManagement();
			

	}
	/**
	 * Change inpatient status.
	 * @param $ticketId
	 * @param $enumStatus
	 * @return nothing
	 * @throw InpatientCoreException if changing fail
	 */
	public function changeCheckinPatientItemStatus($ticketId, $enumStatus) {
			
		$this->inPatientObj->changeCheckinPatientItemStatus($ticketId, $enumStatus);
	}
	/**
	 * Send a request for changing department.
	 * @param $ticketId
	 * @param $fromDepartmentId
	 * @param $toDepartmentId
	 * @return true: send successful, false: send fail
	 * <br>
	 *TODO: now alway success
	 */
	public function sendRequestChangeDepartment($ticketId, $fromDepartmentId, $toDepartmentId) {
		return true;
	}
	/**
	 * check wherether changing department success or not
	 * @param $ticketId
	 * @return
	 * <br>
	 * true : success
	 * <br>
	 * false : fail
	 * <br>
	 *TODO: now allway return true
	 */
	public function getResponseChangeDepartment($ticketId) {
		return true;
	}
	/**
	 *
	 * Finalize a patient, for checking out hostpital.
	 * @param $patientId
	 * @return
	 * @throw InpatientCoreException if finalizing fail
	 */
	protected function finalizePatient($patientId) {
		$inPatientTicketMg = Celini::newORDO("InPatientTicket");
		//get all opening ticket of this patient
		$openingInpatientTk = $inPatientTicketMg->getOpenTicketsInfo($patientId);
		if ($openingInpatientTk == null) {
			return;
		}
		//for each opening ticket, finalize this ticket and record the action check out
		foreach ($openingInpatientTk as $ticket) {
			$this->inPatientObj->finalizeInpatient($ticket['ticket_id']);
		}
	}
	/**
	 * Add a patient into inpatient queue.
	 * @param $patientId
	 * @param $departmentId
	 * @param $dateTime
	 * @param $enumTreatmentType
	 * @param $subStatus
	 * @return ticket id.
	 * @throw
	 * <br>
	 * InPatientCoreErrorCode::COMMON_ERROR If $enumTreatmentType, $subStatus are not supported.
	 * <br>
	 * InPatientCoreErrorCode::IN_PATIENT_EXISTED if this patient already added to inpatient queue of [$departmentId].
	 * <br>
	 */
	private function _checkInPatient($patientId, $departmentId, $dateTime, $consTreatmentType, $subStatus) {
		$this->logger->debug("Start checkInPatient has patient_id [ $patientId ]");

		$checkInSubStatus = Utils::getEnumKey(EnumerationConstant::PATIENT_SUB_STATUS,
		$subStatus);

		$inPatientTicketMg = Celini::newORDO("InPatientTicket");
		//create new ticket for this patient
		$inPatientTicketMg->addNewTicket($patientId, $departmentId);
		$ticketId = $inPatientTicketMg->get_id();
		//add to inpatient queue
		$this->inPatientObj->addNewInpatient($ticketId, $departmentId, $checkInSubStatus);
		//add default bed
		$this->bedMg->addDefaultBedForInputDept($patientId, $departmentId, $ticketId);
		//record checkin
			 
		PatientTransferHistory::record($ticketId, $departmentId, $patientId, CommonConstant::IN_PATIENT,
		CommonConstant::ACTION_CHECKIN, $checkInSubStatus, $dateTime);
		$this->logger->debug("Finish checkInPatient has patient_id [ $patientId ]");
		return $ticketId;	
	}
	public function checkInPatient($patientId, $departmentId, $dateTime, $constTreatmentType, $subStatus) {
		if ($this->inPatientObj->isPatientExisted($patientId, $departmentId) == true) {
			throw new InpatientCoreException("This patient already existed",
			InPatientCoreErrorCode::IN_PATIENT_EXISTED);
		} else {
			return $this->_checkInPatient($patientId, $departmentId, $dateTime, $constTreatmentType, $subStatus);
		}

	}
	/**
	 * Build html form for check out.
	 * @param $ticketId
	 * @return string html form
	 */
	public  function buildCheckOutLeaveHtmlForm($ticketId) {
		$path = $this->controller->view->path;
		$this->controller->view->path = "inpatient_common_form";
		$this->assignCommonVariablies($ticketId);
		$form = $this->controller->view->render('checkout_leave_form.html');
		$this->controller->view->path = $path;
		return $form;
	}
	/**
	 * Assign common varialies to controller.
	 * @param $ticketId
	 * @return nothing.
	 */
	private function assignCommonVariablies($ticketId, $checkOutDepartment=false) {
		//get treatment result enum list
		$treatmentRsList = Utils::getEnumArrayValue(EnumerationConstant::IN_PATIENT_TREATMENT_RESULT);
		if($checkOutDepartment){
			$recovery	=	array(EnumerationConstant::IN_PATIENT_TREATMENT_RESULT_RECOVER, $treatmentRsList[EnumerationConstant::IN_PATIENT_TREATMENT_RESULT_RECOVER]);
			$arrTemp	=	array_diff($treatmentRsList, $recovery);
			$treatmentRsList = $arrTemp;
		}

		$inPatientTicketMg = Celini::newORDO("InPatientTicket");
		$ticketObj = $inPatientTicketMg->getTicketInfo($ticketId);

		//get emr of this patient
		$emr = Celini::newORDO("InPatientEmr");
		$emrInfo =  $emr->getEmrInfo($ticketId);

		$inPatientTicketMg = Celini::newORDO("InPatientTicket");
		$ticketObj = $inPatientTicketMg->getTicketInfo($ticketId);
		
		//get some demographic info
		$patient = Celini::newORDO("Person", $ticketObj['patient_id']);
		$this->controller->assign('patientAge', $patient->getAge());
		$this->controller->assign('patientGender', $patient->getGender());
		$this->controller->assign('patientCareer', $patient->getCareerName());

		if ($ticketObj != null) {
			$this->controller->assign('patientName', $ticketObj['patient_name']);
			$this->controller->assign('patientCode', $ticketObj['patient_code']);
		} else {
			$this->controller->assign('patientName', '');
		}

		if ($emrInfo != null) {

			$this->controller->assign('treatedDoctor', $emrInfo['doctor_name']);
			$this->controller->assign('diagnosis', $emrInfo['diagnosis']);
			$this->controller->assign('icd10PCode', $emrInfo['icd10_p_code']);
			$this->controller->assign('icd10PName', $emrInfo['icd10_p_name']);
			$this->controller->assign('treatmentResultList', $treatmentRsList);

		} else {
			$this->controller->assign('treatedDoctor', '');
			$this->controller->assign('diagnosis', '');
			$this->controller->assign('icd10PCode', '');
			$this->controller->assign('icd10PName', '');
			$this->controller->assign('treatmentResultList', $treatmentRsList);
		}

	}

	/**
	 * Build html form for check out.
	 * @param $ticketId
	 * @return string html form
	 */
	public public function buildCheckOutChangeDeptHtmlForm($ticketId, $currentDepartmentId) {
		$path = $this->controller->view->path;
		$this->controller->view->path = "inpatient_common_form";
		$this->assignCommonVariablies($ticketId, true);
		$departmentList = Celini::newORDO('Department')->getDepartmentList();
		//remove the current dept from dept list allow to moving in.
		unset($departmentList[$currentDepartmentId]);
		$this->controller->assign('departmentList',$departmentList);
		$form = $this->controller->view->render('checkout_changedept_form.html');
		$this->controller->view->path = $path;
		return $form;
	}
	/**
	 * Build html form for check out.
	 * @param $ticketId
	 * @return string html form
	 */
	public public function buildCheckOutDeathHtmlForm($ticketId) {
		$path = $this->controller->view->path;
		$this->controller->view->path = "inpatient_common_form";
		$this->assignCommonVariablies($ticketId);
		$form = $this->controller->view->render('checkout_death_form.html');
		$this->controller->view->path = $path;
		return $form;
	}
	/**
	 * Check out leave
	 * @param $ticketId
	 * @param $constTreatmentType
	 * CommonConstant::IN_PATIENT
	 * <br>
	 * EnumerationConstant::IN_PATIENT_TREATMENT_TYPE_OUT
	 * @param $dateTime
	 * @return nothing.
	 * @throw InpatientCoreException  if fail
	 * <br>
	 * error code:
	 * <br>
	 * InPatientCoreErrorCode::COMMON_ERROR
	 * InPatientCoreErrorCode::COMMON_ERROR
	 *
	 */
	public public function checkOutLeave($ticketId, $constTreatmentType,$dateTime) {
		$this->logger->debug("Start checkOutLeave for patient has ticket [ $ticketId ]");
		//check patient of this ticket could check out or not
		if ($this->canCheckOut($ticketId) == false) {
			throw new InpatientCoreException("Couldnot check-out",
			InPatientCoreErrorCode::IN_PATIENT_COULDNOT_CHECK_OUT);
		}


		$checkOutSubStatus = Utils::getEnumKey(EnumerationConstant::PATIENT_SUB_STATUS,
		EnumerationConstant::PATIENT_SUB_STATUS_CO_LEAVE);


		$inPatientTicketMg = Celini::newORDO("InPatientTicket");
		$ticketObj = $inPatientTicketMg->getTicketInfo($ticketId);
		if ($ticketObj == null) {
			throw new InpatientCoreException("the ticket [ $ticketId ] not exist");
		}
		//this patient can be checked out
		//then do finalizing this patient.
		//finalize bed for this patient
		//close ticket and remove patient from inpatient queue
		$this->finalizePatient($ticketObj['patient_id']);
		//finalize bed
		$this->bedMg->finalizeBedForOutputDept($ticketObj['patient_id']);
		//record action check out for this patient
		PatientTransferHistory::record($ticketId, $ticketObj['department_id'], $ticketObj['patient_id'], CommonConstant::IN_PATIENT,
        CommonConstant::ACTION_CHECKOUT, $checkOutSubStatus, $dateTime);
		$this->logger->debug("Finish checkOutLeave for patient has ticket [ $ticketId ]");

	}


	/**
	 * Check out change department.
	 * @param $ticketId
	 * @throw InpatientCoreException if checking out fail
	 */
	public public function checkOutchangeDepartment($ticketIdCurrDept, $constTreatmentType,$dateTime, $toDepId, $subStatusOfToDept) {
		$this->logger->debug("Start checkOutchangeDepartment for patient has ticket [ $ticketIdCurrDept ]");
		//check patient of this ticket could check out or not
		if ($this->canCheckOut($ticketIdCurrDept) == false) {
			throw new InpatientCoreException("Couldnot check-out",
			InPatientCoreErrorCode::IN_PATIENT_COULDNOT_CHECK_OUT);
		}


		$checkOutSubStatus = Utils::getEnumKey(EnumerationConstant::PATIENT_SUB_STATUS,
		EnumerationConstant::PATIENT_SUB_STATUS_CO_CDEPT);

		$inPatientTicketMg = Celini::newORDO("InPatientTicket");
		$ticketObj = $inPatientTicketMg->getTicketInfo($ticketIdCurrDept);
		if ($ticketObj == null) {
			throw new InpatientCoreException("the ticket [ $ticketIdCurrDept ] not exist");
		}

		//remove patient current dep from queue
		$this->inPatientObj->removeCheckinPatientItem($ticketIdCurrDept);
		//finalize bed
		$this->bedMg->finalizeBedForOutputDept($ticketObj['patient_id']);
		//record action check out department for this patient
		PatientTransferHistory::record($ticketIdCurrDept, $ticketObj['department_id'], $ticketObj['patient_id'], CommonConstant::IN_PATIENT,
        CommonConstant::ACTION_CHECKOUT, $checkOutSubStatus, $dateTime);

		//check-in to new dept
		$this->_checkInPatient($ticketObj['patient_id'],$toDepId,$dateTime,$constTreatmentType, $subStatusOfToDept);

		$this->logger->debug("Finish checkOutchangeDepartment for patient has ticket [ $ticketIdCurrDept ]");
	}

	/**
	 * Check out leave.
	 * @param $ticketId
	 * @throw InpatientCoreException if checking out fail
	 */
	public public function checkOutDeath($ticketId, $constTreatmentType,$dateTime) {
		$this->logger->debug("Start checkOutDeath for patient has ticket [ $ticketId ]");
		//check patient of this ticket could check out or not
		if ($this->canCheckOut($ticketId) == false) {
			throw new InpatientCoreException("Couldnot check-out",
			InPatientCoreErrorCode::IN_PATIENT_COULDNOT_CHECK_OUT);
		}

		
		
		
		$checkOutSubStatus = Utils::getEnumKey(EnumerationConstant::PATIENT_SUB_STATUS,
		EnumerationConstant::PATIENT_SUB_STATUS_CO_DEATH);
		

		$inPatientTicketMg = Celini::newORDO("InPatientTicket");
		$ticketObj = $inPatientTicketMg->getTicketInfo($ticketId);
		if ($ticketObj == null) {
			throw new InpatientCoreException("the ticket [ $ticketId ] not exist");
		}
		//this patient can be checked out then do finalizing this patient.
		//finalize bed for this patient
		//close ticket and remove patient from inpatient queue
		$this->finalizePatient($ticketObj['patient_id']);


		//finalize bed
		$this->bedMg->finalizeBedForOutputDept($ticketObj['patient_id']);
			


		//record action check out for this patient
		PatientTransferHistory::record($ticketId, $ticketObj['department_id'], $ticketObj['patient_id'], CommonConstant::IN_PATIENT,
        CommonConstant::ACTION_CHECKOUT, $checkOutSubStatus, $dateTime);
		
		
		$this->logger->debug("Finish checkOutDeath for patient has ticket [ $ticketId ]");

	}
	
	public function buildTestTicketInfoCashierHtml($patientId) {
		$inTicketItemObj = Celini::newOrdo("InTicketItem");
        $list = $inTicketItemObj->listTestTicketInfoByPatient($patientId);
        $total = array('original_price'=>0,'insurance_price'=>0,'patient_price'=>0);
	    foreach ($list as $item) {
	    	$total['original_price'] += $item['original_price'];
	    	$total['insurance_price'] += $item['insurance_price'];
	    	$total['patient_price'] += $item['patient_price'];
        }
        $total['original_price'] = L10nHelper::renderNumber($total['original_price'],0);
        $total['insurance_price'] = L10nHelper::renderNumber($total['insurance_price'],0);
        $total['patient_price'] = L10nHelper::renderNumber($total['patient_price'],0);
        
        InTicketItem::normalizeTestTicketDataForDisplay($list);
        $path = $this->controller->view->path;
        $this->controller->view->path = "ticket_test";
        
        $this->controller->assign('listTestTicketInfo', $list);
        $this->controller->assign('total', $total);        
        $form = $this->controller->view->render('test_ticket.html');
        $this->controller->view->path = $path;
        return $form;		
	}
	
	
    public function buildTestTicketDetailCashierHtml($testDiagnosisTicketId) {
    	$testTicketManagerment = new TestDiagnosisTicketManagement();
        $listAssignedTestItem = $testTicketManagerment->listOfAssignedTestItem($testDiagnosisTicketId);
        AssigedTestItem::normalizeData4Display($listAssignedTestItem);
        $assignedTestArr = $testTicketManagerment->buildTestArray4Print($listAssignedTestItem);
        $path = $this->controller->view->path;
        $this->controller->view->path = "ticket_test";
        $this->controller->assign('assignedTestArr', $assignedTestArr );
        $form = $this->controller->view->render('test_detail.html');
        $this->controller->view->path = $path;
        return $form;
    }

	/**
	 * Check wherether patient has ticket could be checked out.
	 * @param $ticketId
	 * @return
	 * TODO now alway checkout(true)
	 */
	public function canCheckOut($ticketId) {
		return true;
	}
}
?>